package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.model.wemedia.vos.WmNewsVo;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.utils.threadlocal.WmThreadLocalUtil;
import com.heima.wemedia.service.WmNewsTaskService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {
    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Autowired
    private WmMaterialMapper wmMaterialMapper;
    @Autowired
    private WmNewsTaskService wmNewsTaskService;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;
    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;

    /**
     * 文章审核，修改状态
     * @param
     * @param dto
     * @return
     */
    @Override
    public ResponseResult updateStatus(NewsAuthDto dto) {
        //1.检查参数
        if(dto == null || dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2.查询文章信息
        WmNews wmNews = getById(dto.getId());
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //3.修改文章的状态
        wmNews.setStatus(dto.getStatus());
        if(StringUtils.isNotBlank(dto.getMsg())){
            wmNews.setReason(dto.getMsg());
        }
        updateById(wmNews);

        //审核成功，则需要创建app端文章数据，并修改自媒体文章
        if(dto.getStatus() == 4){
            //创建app端文章数据
            ResponseResult responseResult = wmNewsAutoScanService.saveAppArticle(wmNews);
            if(responseResult.getCode().equals(200)){
                wmNews.setArticleId((Long) responseResult.getData());
                wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
                updateById(wmNews);
            }
        }

        //4.返回
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 后台端文章详情
     * @param id
     * @return
     */
    @Override
    public ResponseResult findWmNewsVo(Integer id) {
        //1.检查参数
        if(id == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2.查询文章信息
        WmNews wmNews = getById(id);
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //3.查询用户信息
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());

        //4.封装vo返回
        WmNewsVo vo = new WmNewsVo();
        //属性拷贝
        BeanUtils.copyProperties(wmNews,vo);
        if(wmUser != null){
            vo.setAuthorName(wmUser.getName());
        }

        ResponseResult responseResult = new ResponseResult().ok(vo);

        return responseResult;
    }

    /**
     * 后台端查询文章列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findAll(NewsAuthDto dto) {
        //1.参数检查
        dto.checkParam();

        //记录当前页
        int currentPage = dto.getPage();

        //2.分页查询+count查询
        dto.setPage((dto.getPage()-1)*dto.getSize());
        List<WmNewsVo> wmNewsVoList = wmNewsMapper.findListAndPage(dto);
        int count = wmNewsMapper.findListCount(dto);

        //3.结果返回
        ResponseResult responseResult = new PageResponseResult(currentPage,dto.getSize(),count);
        responseResult.setData(wmNewsVoList);
        return responseResult;
    }

    /**
     * 发布文章
     * @param dto
     * @return
     */
    @Override
    public ResponseResult submit(WmNewsDto dto) {
        WmUser user = WmThreadLocalUtil.getUser();
        if (user == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        if (dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //排版状态0是无图,1是单图,3是多图,-1是自动
        if (dto.getType() == -1){
            dto.setType(null);
        }
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto,wmNews);


        //封面图片集合
        List<String> imagesList = dto.getImages();
        if (imagesList != null && imagesList.size()>0){
            String imgStr = StringUtils.join(imagesList, ',');
            wmNews.setImages(imgStr);
        }
        //基本信息保存或者更改到草稿箱
        saveOrUpdateNews(wmNews);

        //文章内容图片地址集合
        ArrayList<String> oneImage = new ArrayList<>();
        String content = dto.getContent();
        List<Map> maps = JSON.parseArray(content, Map.class);
        for (Map map : maps) {
            if ("image".equals(map.get("type"))){
                oneImage.add((String)map.get("value"));
            }
        }
        //4.1 内容中图片与文章的关系
        saveNewsMaterial(wmNews,(short)0,oneImage);


        //4.2 封面图片与文章的关系
        fengmianImageToNews(wmNews,dto,imagesList,(short)1);

        //调用审核服务
        //wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
        //调用远程服务添加任务
        wmNewsTaskService.addNewsToTask(wmNews.getId(),wmNews.getPublishTime());


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 上下架文章
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        if (dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //修改文章上下架状态
        WmNews wmNews = this.getById(dto.getId());
        if (wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }
        if (wmNews.getStatus() != WmNews.Status.PUBLISHED.getCode()){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"文章未审核通过");
        }
        wmNews.setEnable(dto.getEnable());

        this.updateById(wmNews);
        //得到文章id和状态发给kafka
        if(wmNews.getArticleId() != null) {
            Map<String, Object> map = new HashMap<>();
            map.put("articleId", wmNews.getArticleId());
            map.put("enable", wmNews.getEnable());
            kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(map));
        }
        return ResponseResult.okResult(null);
    }


    /**
     * 抽取的第四个方法，关联封面图片与文章的关系，操作中间表
     *  如果封面类型是自动的话，从文章内容中图片进行操作
     *      如果文章内容图片个数大于1，小于3的话，则认为单图
     *      如果文章内容图片个数大于等于3的话，则认为多图
     *       如果文章内容图片个数，则认为是无图
     *
     * @param wmNews
     * @param type
     */
    private void fengmianImageToNews(WmNews wmNews, WmNewsDto dto, List<String> imagesList, short type) {
        //1.获取封面图片,这是为了设置关联id
        List<String> imagess = dto.getImages();

        //自动
        if(dto.getType()==null){
            if(imagesList.size()>=1 && imagesList.size()<3){
                //取出第一张图片作为封面
                imagesList= (List<String>) imagesList.stream().limit(1).collect(Collectors.toList());
                //单图设置类型
                wmNews.setType((short) 1);
            }else if(imagesList.size()>=3){
                imagesList= (List<String>) imagesList.stream().limit(3).collect(Collectors.toList());
                //多图设置类型
                wmNews.setType((short) 3);
            }else{
                wmNews.setType((short) 0);
            }

            wmNews.setImages(StringUtils.join(imagesList, ","));
            updateById(wmNews);
        }
        //否则，直接插入到中间表中
        saveNewsMaterial(wmNews, type, imagess);
    }

    /**
     * 文章图片关联
     * @param wmNews
     * @param type
     * @param images
     */
    private void saveNewsMaterial(WmNews wmNews, short type, List<String> images) {
        if (images != null&&images.size()>0){

            List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(Wrappers
                    .lambdaQuery(WmMaterial.class)
                    .in(WmMaterial::getUrl,images));
            ArrayList<Integer> list = new ArrayList<>();
            for (WmMaterial wmMaterial : wmMaterials) {
                    list.add(wmMaterial.getId());
            }
            wmNewsMaterialMapper.saveRelations(list,wmNews.getId(),type);
        }
    }

    /**
     * 文章保存或者更新到草稿
     * @param wmNews
     */
    private void saveOrUpdateNews(WmNews wmNews) {
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
        if (wmNews.getId()!=null){
            wmNewsMaterialMapper.delete(Wrappers.lambdaQuery(WmNewsMaterial.class)
                    .eq(WmNewsMaterial::getNewsId,wmNews.getId()));
            updateById(wmNews);
        } else {
            save(wmNews);
        }
    }


    /**
     * 分页查询
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findList(WmNewsPageReqDto dto) {
        if (dto ==null){
            ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.checkParam();
        WmUser user = WmThreadLocalUtil.getUser();
        if(user == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //构造分页条件
        IPage<WmNews> page = new Page<>(dto.getPage(),dto.getSize());
        //构造条件
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        //状态精确查询
        if (dto.getStatus() != null){
            queryWrapper.eq(WmNews::getStatus,dto.getStatus());
        }
        //频道精确查询
        if(dto.getChannelId() != null){
            queryWrapper.eq(WmNews::getChannelId,dto.getChannelId());
        }

        //时间范围查询
        if(dto.getBeginPubdate()!=null && dto.getEndPubdate()!=null){
            queryWrapper.between(WmNews::getPublishTime,dto.getBeginPubdate(),dto.getEndPubdate());
        }

        //关键字模糊查询
        if(StringUtils.isNotBlank(dto.getKeyword())){
            queryWrapper.like(WmNews::getTitle,dto.getKeyword());
        }
        //查询当前登录用户的文章
        queryWrapper.eq(WmNews::getUserId,user.getId());
        //发布时间倒序查询
        queryWrapper.orderByDesc(WmNews::getCreatedTime);

        page(page,queryWrapper);
        //3.结果返回
        ResponseResult responseResult = new PageResponseResult(dto.getPage(),dto.getSize(),(int)page.getTotal());
        responseResult.setHost("");
        responseResult.setData(page.getRecords());

        return responseResult;
    }


}
